import {
  ElButton,
  ElCol,
  ElDialog,
  ElForm,
  ElFormItem,
  ElInput,
  ElInputNumber,
  ElRadio,
  ElRadioGroup,
  ElRow,
  ElSpace,
  ElTreeSelect,
  type FormInstance,
  type FormRules
} from 'element-plus'
import { computed, defineComponent, reactive, toRefs } from 'vue'

import { type IMenuListItem, menuApi } from '@/apis'
import { IconVirtualPick } from '@/components'
import { genRandomID, objAssign } from '@/utils'

import { useMenuTree } from '../../hooks'
import {
  cacheOptions,
  formData,
  type IFormData,
  menuDialogProps,
  menuTypeOptions,
  visibleOptions
} from './MenuDialog.define'

export default defineComponent({
  name: 'MenuDialog',
  props: menuDialogProps(),
  emits: ['success'],
  setup(_, { emit }) {
    const state = reactive({
      show: false,
      isAdd: true,
      formRef: {} as FormInstance,
      formModel: formData(),
      formRules: {
        menuName: [{ required: true, message: '请输入菜单名称' }],
        orderNum: [{ required: true, message: '请输入显示顺序' }],
        path: [{ required: true, message: '请输入路由地址' }]
      } as FormRules<IFormData>,
      selectedRecord: {} as IMenuListItem,
      submitLoading: false
    })

    const { getMenuTree, ...menuTreeRestHook } = useMenuTree()

    const dialogTitle = computed(() => (state.isAdd ? '添加菜单' : '修改菜单'))
    const formItems = computed<string[][]>(() => {
      let res: string[][] = []

      switch (state.formModel.menuType) {
        case 'M':
          res = [
            ['FormItemIcon'],
            ['FormItemPath', 'FormItemStatus'],
            ['FormItemVisible']
          ]
          break
        case 'C':
          res = [
            ['FormItemIcon'],
            ['FormItemPath', 'FormItemComponent'],
            ['FormItemRedirect', 'FormItemPerms'],
            ['FormItemVisible', 'FormItemStatus'],
            ['FormItemCache']
          ]
          break
        case 'F':
          res = [['FormItemPerms']]
          break
        default:
          break
      }

      return res
    })

    function open(data = {} as Partial<IMenuListItem>, isAdd = true) {
      objAssign(state.formModel, data)
      Object.assign(state.selectedRecord, data)
      state.isAdd = isAdd
      state.show = true

      getMenuTree()
    }

    function handleClose() {
      state.show = false
      state.submitLoading = false
      state.selectedRecord = Object.create(null)
      state.formModel = formData()
      state.formRef.clearValidate()
    }

    function handleSubmit() {
      state.formRef.validate(async valid => {
        if (valid) {
          try {
            state.submitLoading = true

            if (state.isAdd) {
              await menuApi.createMenu(state.formModel)
            } else {
              await menuApi.updateMenu(state.selectedRecord.id, state.formModel)
            }

            handleClose()
            emit('success')
          } catch (error) {
            state.submitLoading = false
          }
        }
      })
    }

    return {
      ...toRefs(state),
      ...menuTreeRestHook,
      dialogTitle,
      formItems,
      cacheOptions,
      menuTypeOptions,
      visibleOptions,
      open,
      handleClose,
      handleSubmit
    }
  },
  render() {
    const formItemMap = {
      FormItemIcon: () => (
        <ElCol span={24}>
          <ElFormItem label="菜单图标">
            <IconVirtualPick v-model={this.formModel.icon} />
          </ElFormItem>
        </ElCol>
      ),
      FormItemPath: () => (
        <ElCol span={12}>
          <ElFormItem label="路由地址" prop="path">
            <ElInput v-model={this.formModel.path} />
          </ElFormItem>
        </ElCol>
      ),
      FormItemComponent: () => (
        <ElCol span={12}>
          <ElFormItem label="组件路径" prop="component">
            <ElInput v-model={this.formModel.component} />
          </ElFormItem>
        </ElCol>
      ),
      FormItemRedirect: () => (
        <ElCol span={12}>
          <ElFormItem label="跳转地址" prop="redirect">
            <ElInput v-model={this.formModel.redirect} />
          </ElFormItem>
        </ElCol>
      ),
      FormItemVisible: () => (
        <ElCol span={12}>
          <ElFormItem label="显示状态" prop="visible">
            <ElRadioGroup v-model={this.formModel.visible}>
              {this.visibleOptions.map(item => (
                <ElRadio key={item.value} value={item.value}>
                  {item.label}
                </ElRadio>
              ))}
            </ElRadioGroup>
          </ElFormItem>
        </ElCol>
      ),
      FormItemCache: () => (
        <ElCol span={12}>
          <ElFormItem label="是否缓存" prop="isCache">
            <ElRadioGroup v-model={this.formModel.isCache}>
              {this.cacheOptions.map(item => (
                <ElRadio key={item.value} value={item.value}>
                  {item.label}
                </ElRadio>
              ))}
            </ElRadioGroup>
          </ElFormItem>
        </ElCol>
      ),
      FormItemStatus: () => (
        <ElCol span={12}>
          <ElFormItem label="菜单状态" prop="status">
            <ElRadioGroup v-model={this.formModel.status}>
              {this.statusOptions.map(item => (
                <ElRadio key={item.value} value={item.value}>
                  {item.label}
                </ElRadio>
              ))}
            </ElRadioGroup>
          </ElFormItem>
        </ElCol>
      ),
      FormItemPerms: () => (
        <ElCol span={12}>
          <ElFormItem label="权限字符" prop="perms">
            <ElInput v-model={this.formModel.perms} />
          </ElFormItem>
        </ElCol>
      )
    }

    return (
      <ElDialog
        v-model={this.show}
        title={this.dialogTitle}
        beforeClose={this.handleClose}
        width="600px"
        destroyOnClose
      >
        {{
          default: () => (
            <ElForm
              ref={(e: any) => (this.formRef = e)}
              v-loading={this.treeLoading}
              model={this.formModel}
              rules={this.formRules}
              labelWidth="100px"
            >
              <ElFormItem label="上级菜单" prop="parentId">
                <ElTreeSelect
                  ref={(e: any) => (this.menuTreeRef = e)}
                  v-model={this.formModel.parentId}
                  nodeKey="key"
                  data={this.menuTree}
                  props={{
                    label: 'title',
                    children: 'children'
                  }}
                  checkStrictly
                  clearable
                  placeholder="请选择上级菜单"
                  style="width: 100%"
                >
                  {{
                    // @ts-ignore
                    default: ({ data: { title, children } }) => (
                      <>
                        <span>{title}</span>
                        {children.length ? (
                          <span
                            style={{
                              color: '#999'
                            }}
                          >
                            ({children.length})
                          </span>
                        ) : null}
                      </>
                    )
                  }}
                </ElTreeSelect>
              </ElFormItem>
              <ElFormItem label="菜单类型" prop="menuType">
                <ElRadioGroup v-model={this.formModel.menuType}>
                  {this.menuTypeOptions.map(v => (
                    <ElRadio key={v.value} value={v.value}>
                      {v.label}
                    </ElRadio>
                  ))}
                </ElRadioGroup>
              </ElFormItem>
              <ElRow gutter={15}>
                <ElCol span={12}>
                  <ElFormItem label="菜单名称" prop="menuName">
                    <ElInput v-model={this.formModel.menuName} />
                  </ElFormItem>
                </ElCol>
                <ElCol span={12}>
                  <ElFormItem label="显示顺序" prop="orderNum">
                    <ElInputNumber v-model={this.formModel.orderNum} min={0} />
                  </ElFormItem>
                </ElCol>
              </ElRow>
              {this.formItems.map(v => (
                <ElRow gutter={15} key={genRandomID()}>
                  {/* @ts-ignore */}
                  {v.map(item => formItemMap[item]())}
                </ElRow>
              ))}
            </ElForm>
          ),
          footer: () => (
            <ElSpace>
              <ElButton onClick={this.handleClose}>取消</ElButton>
              <ElButton
                type="primary"
                loading={this.submitLoading}
                onClick={this.handleSubmit}
              >
                确定
              </ElButton>
            </ElSpace>
          )
        }}
      </ElDialog>
    )
  }
})
